package com.aps.service.excel;

import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.regex.Pattern;

/**
 * Excel数据验证服务
 * 支持可扩展的验证规则
 */
@Service
public class ExcelValidationService {
    
    private final Map<String, List<ValidationRule>> customRules = new HashMap<>();
    
    /**
     * 验证数据
     */
    public List<ExcelValidationError> validateData(List<Map<String, Object>> rawData, 
                                                   Class<?> entityClass, 
                                                   ExcelImportStrategy strategy) {
        List<ExcelValidationError> errors = new ArrayList<>();
        
        for (Map<String, Object> rowData : rawData) {
            Integer rowIndex = (Integer) rowData.get("_rowIndex");
            
            // 基础字段验证
            errors.addAll(validateFields(rowData, entityClass, rowIndex));
            
            // 自定义业务验证
            errors.addAll(strategy.validateBusinessRules(rowData, rowIndex));
            
            // 自定义规则验证
            errors.addAll(validateCustomRules(rowData, entityClass.getSimpleName(), rowIndex));
        }
        
        return errors;
    }
    
    /**
     * 字段级验证
     */
    private List<ExcelValidationError> validateFields(Map<String, Object> rowData, Class<?> entityClass, Integer rowIndex) {
        List<ExcelValidationError> errors = new ArrayList<>();
        Field[] fields = entityClass.getDeclaredFields();
        
        for (Field field : fields) {
            String fieldName = field.getName();
            Object value = rowData.get(fieldName);
            
            // 必填验证
            ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
            if (annotation != null && annotation.required() && isEmptyValue(value)) {
                errors.add(new ExcelValidationError(rowIndex, fieldName, value, "必填字段不能为空"));
                continue;
            }
            
            // 类型验证
            if (value != null && !isEmptyValue(value)) {
                String typeError = validateFieldType(value, field.getType());
                if (typeError != null) {
                    errors.add(new ExcelValidationError(rowIndex, fieldName, value, typeError));
                }
            }
            
            // 格式验证
            if (annotation != null && !annotation.format().isEmpty() && value != null) {
                String formatError = validateFormat(value, annotation.format());
                if (formatError != null) {
                    errors.add(new ExcelValidationError(rowIndex, fieldName, value, formatError));
                }
            }
        }
        
        return errors;
    }
    
    /**
     * 类型验证
     */
    private String validateFieldType(Object value, Class<?> targetType) {
        if (value == null) return null;
        
        try {
            String strValue = value.toString().trim();
            
            if (targetType == Integer.class || targetType == int.class) {
                Double.valueOf(strValue).intValue();
            } else if (targetType == Long.class || targetType == long.class) {
                Double.valueOf(strValue).longValue();
            } else if (targetType == Double.class || targetType == double.class) {
                Double.valueOf(strValue);
            } else if (targetType == Boolean.class || targetType == boolean.class) {
                if (!"true".equalsIgnoreCase(strValue) && !"false".equalsIgnoreCase(strValue) 
                    && !"是".equals(strValue) && !"否".equals(strValue)
                    && !"1".equals(strValue) && !"0".equals(strValue)) {
                    return "布尔值格式错误，请输入：true/false、是/否、1/0";
                }
            } else if (targetType == LocalDate.class) {
                if (!(value instanceof Date)) {
                    LocalDate.parse(strValue);
                }
            } else if (targetType == LocalDateTime.class) {
                if (!(value instanceof Date)) {
                    LocalDateTime.parse(strValue);
                }
            }
            
            return null;
        } catch (Exception e) {
            return "数据类型错误：" + e.getMessage();
        }
    }
    
    /**
     * 格式验证
     */
    private String validateFormat(Object value, String format) {
        if (value == null || format.isEmpty()) return null;
        
        String strValue = value.toString().trim();
        
        try {
            // 正则表达式验证
            if (format.startsWith("regex:")) {
                String regex = format.substring(6);
                if (!Pattern.matches(regex, strValue)) {
                    return "格式不正确，要求格式：" + regex;
                }
            }
            // 长度验证
            else if (format.startsWith("length:")) {
                String[] parts = format.substring(7).split(",");
                int min = Integer.parseInt(parts[0]);
                int max = parts.length > 1 ? Integer.parseInt(parts[1]) : Integer.MAX_VALUE;
                
                if (strValue.length() < min || strValue.length() > max) {
                    return String.format("长度应在%d-%d之间", min, max);
                }
            }
            // 数值范围验证
            else if (format.startsWith("range:")) {
                String[] parts = format.substring(6).split(",");
                double min = Double.parseDouble(parts[0]);
                double max = parts.length > 1 ? Double.parseDouble(parts[1]) : Double.MAX_VALUE;
                double numValue = Double.parseDouble(strValue);
                
                if (numValue < min || numValue > max) {
                    return String.format("数值应在%.2f-%.2f之间", min, max);
                }
            }
            // 枚举值验证
            else if (format.startsWith("enum:")) {
                String[] values = format.substring(5).split(",");
                if (!Arrays.asList(values).contains(strValue)) {
                    return "值必须是以下之一：" + String.join(", ", values);
                }
            }
            
            return null;
        } catch (Exception e) {
            return "格式验证失败：" + e.getMessage();
        }
    }
    
    /**
     * 自定义规则验证
     */
    private List<ExcelValidationError> validateCustomRules(Map<String, Object> rowData, String entityName, Integer rowIndex) {
        List<ExcelValidationError> errors = new ArrayList<>();
        List<ValidationRule> rules = customRules.get(entityName);
        
        if (rules != null) {
            for (ValidationRule rule : rules) {
                ValidationResult result = rule.validate(rowData);
                if (!result.isValid()) {
                    errors.add(new ExcelValidationError(rowIndex, result.getField(), 
                        rowData.get(result.getField()), result.getMessage()));
                }
            }
        }
        
        return errors;
    }
    
    /**
     * 添加自定义验证规则
     */
    public void addValidationRule(String entityName, ValidationRule rule) {
        customRules.computeIfAbsent(entityName, k -> new ArrayList<>()).add(rule);
    }
    
    /**
     * 判断值是否为空
     */
    private boolean isEmptyValue(Object value) {
        if (value == null) return true;
        if (value instanceof String) return ((String) value).trim().isEmpty();
        return false;
    }
}

/**
 * 验证规则接口
 */
interface ValidationRule {
    ValidationResult validate(Map<String, Object> rowData);
}

/**
 * 验证结果
 */
class ValidationResult {
    private boolean valid;
    private String field;
    private String message;
    
    public ValidationResult(boolean valid, String field, String message) {
        this.valid = valid;
        this.field = field;
        this.message = message;
    }
    
    public static ValidationResult success() {
        return new ValidationResult(true, null, null);
    }
    
    public static ValidationResult failure(String field, String message) {
        return new ValidationResult(false, field, message);
    }
    
    // getters
    public boolean isValid() { return valid; }
    public String getField() { return field; }
    public String getMessage() { return message; }
}

/**
 * Excel验证错误
 */
class ExcelValidationError {
    private Integer row;
    private String field;
    private Object value;
    private String message;
    
    public ExcelValidationError(Integer row, String field, Object value, String message) {
        this.row = row;
        this.field = field;
        this.value = value;
        this.message = message;
    }
    
    // getters and setters
    public Integer getRow() { return row; }
    public void setRow(Integer row) { this.row = row; }
    
    public String getField() { return field; }
    public void setField(String field) { this.field = field; }
    
    public Object getValue() { return value; }
    public void setValue(Object value) { this.value = value; }
    
    public String getMessage() { return message; }
    public void setMessage(String message) { this.message = message; }
}

/**
 * 常用验证规则实现
 */
class CommonValidationRules {
    
    /**
     * 工单编号唯一性验证
     */
    public static ValidationRule workOrderUniqueRule() {
        return rowData -> {
            String workOrderId = (String) rowData.get("workOrderId");
            if (workOrderId != null) {
                // 这里应该查询数据库检查唯一性
                // 示例：检查是否已存在
                boolean exists = checkWorkOrderExists(workOrderId);
                if (exists) {
                    return ValidationResult.failure("workOrderId", "工单编号已存在");
                }
            }
            return ValidationResult.success();
        };
    }
    
    /**
     * 交付日期合理性验证
     */
    public static ValidationRule deliveryDateRule() {
        return rowData -> {
            Object deliveryDate = rowData.get("deliveryDate");
            if (deliveryDate != null) {
                LocalDate date;
                if (deliveryDate instanceof Date) {
                    date = ((Date) deliveryDate).toInstant().atZone(java.time.ZoneId.systemDefault()).toLocalDate();
                } else {
                    try {
                        date = LocalDate.parse(deliveryDate.toString());
                    } catch (Exception e) {
                        return ValidationResult.failure("deliveryDate", "日期格式错误");
                    }
                }
                
                if (date.isBefore(LocalDate.now())) {
                    return ValidationResult.failure("deliveryDate", "交付日期不能早于当前日期");
                }
            }
            return ValidationResult.success();
        };
    }
    
    /**
     * 数量范围验证
     */
    public static ValidationRule quantityRangeRule(int min, int max) {
        return rowData -> {
            Object quantity = rowData.get("quantity");
            if (quantity != null) {
                try {
                    int qty = Integer.parseInt(quantity.toString());
                    if (qty < min || qty > max) {
                        return ValidationResult.failure("quantity", 
                            String.format("数量应在%d-%d之间", min, max));
                    }
                } catch (NumberFormatException e) {
                    return ValidationResult.failure("quantity", "数量必须是整数");
                }
            }
            return ValidationResult.success();
        };
    }
    
    /**
     * 优先级验证
     */
    public static ValidationRule priorityRule() {
        return rowData -> {
            String priority = (String) rowData.get("priority");
            if (priority != null) {
                if (!"高".equals(priority) && !"中".equals(priority) && !"低".equals(priority)) {
                    return ValidationResult.failure("priority", "优先级只能是：高、中、低");
                }
            }
            return ValidationResult.success();
        };
    }
    
    // 模拟数据库查询
    private static boolean checkWorkOrderExists(String workOrderId) {
        // 实际实现中应该查询数据库
        return false;
    }
}
